package com.sf.fy.uav.applet.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.sf.fy.uav.applet.IntraCityServiceClient;
import com.sf.fy.uav.applet.config.DelayQueue;
import com.sf.fy.uav.applet.login.service.LoginService;
import com.sf.fy.uav.applet.service.OrderService;
import com.sf.fy.uav.common.exception.BusinessException;
import com.sf.fy.uav.common.response.order.PrintDataResponse;
import com.sf.fy.uav.common.utils.*;
import com.sf.fy.uav.common.awt.JwtUtil;
import com.sf.fy.uav.common.enums.*;
import com.sf.fy.uav.common.request.order.*;
import com.sf.fy.uav.controller.UserCouponRest;
import com.sf.fy.uav.good.controller.GoodsTypeRest;
import com.sf.fy.uav.good.entity.TaskGoods;
import com.sf.fy.uav.good.mapper.CityGoodsTypeMapper;
import com.sf.fy.uav.good.mapper.TaskGoodsMapper;
import com.sf.fy.uav.mapper.*;
import com.sf.fy.uav.order.controller.*;
import com.sf.fy.uav.order.entity.*;
import com.sf.fy.uav.order.mapper.*;
import com.sf.fy.uav.order.service.IFeedbackService;
import com.sf.fy.uav.order.service.IOrderInfoService;
import com.sf.fy.uav.rest.ActivityRest;
import com.sf.fy.uav.rest.PromotionStatisticsRest;
import com.sf.fy.uav.rest.controller.TtTesTerminalRest;
import com.sf.fy.uav.rest.entity.TtTesTerminal;
import com.sf.fy.uav.sms.rest.WxAppletRest;
import com.sf.fy.uav.task.controller.TaskStatusLogRest;
import com.sf.fy.uav.task.entity.TaskStatusLog;
import com.sf.fy.uav.task.mapper.TaskStatusLogMapper;
import com.sf.fy.uav.task.rest.IntraCityRest;
import com.sf.fy.uav.user.controller.UserCompanyRest;
import com.sf.fy.uav.user.entity.UserCompany;
import com.sf.fy.uav.user.mapper.RewardBillMapper;
import com.sf.fy.uav.user.mapper.UserCompanyMapper;
import com.sf.fy.uav.user.mapper.UserMapper;
import com.sf.fy.uav.user.rest.UserRest;
import com.sf.fy.uav.withdrawal.mapper.WithdrawalStatisticsMapper;
import com.sf.fy.uav.withdrawal.rest.WithdrawalStatisticsRest;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * @author LTQ
 */
@Service
public class OrderServiceImpl implements OrderService {
    private final static Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);


    @Autowired
    private UserCompanyRest userCompanyRest;

    @Autowired
    private OrderInfoRest orderInfoRest;


    @Autowired
    private UserCompanyMapper userCompanyMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IOrderInfoService iOrderInfoService;

    @Autowired
    private IntraCityServiceClient intraCityServiceClient;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private IntraCityRest intraCityRest;

    @Autowired
    private WithdrawalStatisticsRest withdrawalStatisticsRest;

    @Autowired
    private FeedbackTypeRest feedbackTypeRest;
    @Value("${count.down.pending_items:7}")
    private Integer countDownPendingItems;
    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private TaskStatusLogMapper taskStatusLogMapper;

    @Autowired
    private OrderExtraController orderExtraController;

    @Autowired
    private PaySettingMapper paySettingMapper;

    @Autowired
    private TaskGoodsMapper taskGoodsMapper;

    @Autowired
    private TtTesTerminalRest ttTesTerminalRest;

    @Autowired
    private TaskStatusLogRest taskStatusLogRest;

    @Autowired
    private FeedbackTypeMapper feedbackTypeMapper;

    @Autowired
    private InvitationCodeMapper invitationCodeMapper;

    @Autowired
    private FeedbackStatusLogMapper feedbackStatusLogMapper;

    @Autowired
    private PromotionRecordsMapper promotionRecordsMapper;

    @Autowired
    private PromotionStatisticsMapper promotionStatisticsMapper;

    @Autowired
    private PromotionStatisticsRest promotionStatisticsRest;

    @Autowired
    private PaySettingRest paySettingRest;

    @Autowired
    private PricingRest pricingRest;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FeedbackRest feedbackRest;

    @Autowired
    private FeedbackMapper feedbackMapper;

    @Autowired
    private IFeedbackService iFeedbackService;

    @Autowired
    private FeedbackStatusLogRest feedbackStatusLogRest;

    @Autowired
    private CityGoodsTypeMapper cityGoodsTypeMapper;

    @Autowired
    private GoodsTypeRest goodsTypeRest;

    @Autowired
    private InvitationRecordMapper invitationRecordMapper;

    @Autowired
    private ActivityRest activityRest;

    @Autowired
    private UserRest userRest;

    @Value("${wx.appid:wxe6b1552baf2f3303}")
    private String appid;

    @Value("${wx.update-status-template-id:DyZzQXtOw2iXdd63ZETf-40AVO_q8Ip305yplDfs2qc}")
    private String updateStatusTemplateId;

    @Value("${wx.delivery-completed-template-id:2g5ww9uT3wlOhfKdvA34E4OOACSfvjHvXuZCDF60LK8}")
    private String deliveryCompletedTemplateId;


    SimpleDateFormat sdf = new SimpleDateFormat("YYYY年MM月dd日 HH:mm:ss");


    @Value("${pay.notify-url:http://127.0.0.1:8080/trade/callback}")
    private String notifyUrl;


    @Value("${callback.url:https://ie-uocs-out.sit.sf-express.com:4433/uocs-intracity/}")
    private String callbackUrl;

    @Autowired
    private DelayQueue delayQueue;

    @Autowired
    private BillRest billRest;

    @Autowired
    private BillMapper billMapper;

    @Autowired
    private WxAppletRest wxAppletRest;

    @Autowired
    private LoginService loginService;

    @Autowired
    private RewardBillMapper rewardBillMapper;

    @Autowired
    private WithdrawalStatisticsMapper withdrawalStatisticsMapper;

    @Autowired
    private UserCouponMapper userCouponMapper;

    @Autowired
    private PhoneEncoderUtil phoneEncoderUtil;

    @Value("${lock.try_time:3}")
    private long lockTryTime;

    @Autowired
    private UserCouponRest userCouponRest;

    @Autowired
    private CouponMapper couponMapper;

    @Value("${express.fee:20}")
    private BigDecimal expressFee;

    @Autowired
    private ExpenseDetailsMapper expenseDetailsMapper;


    @Override
    public BigDecimal getAvailableCredit() {
        String userId = JwtUtil.getUserId();
        UserCompany userCompany = userCompanyRest.getByUserId(userId);
        Byte status = userCompany.getStatus();
        if (!status.equals(UserCompanyStatusEnum.NORMAL.getValue())) {
            throw new RuntimeException("公司状态异常，请联系管理员");
        }
        BigDecimal monthlyCreditLimit = userCompany.getMonthlyCreditLimit();
        BigDecimal usedCreditLimit = userCompany.getUsedCreditLimit();

        BigDecimal availableCredit = monthlyCreditLimit.subtract(usedCreditLimit);

        return availableCredit;
    }

    @Override
    public Date cancelExpressOrder(String id, String processedBy) {
        Lock lock = null;
        try {
            lock = redissonClient.getLock(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_INVENTORY_CHANGE + id);
            //也可以指定锁时间的
            Boolean b = lock.tryLock(lockTryTime, TimeUnit.SECONDS);
            if (b) {
                Date date = new Date();
                OrderInfo orderInfo = orderInfoMapper.selectById(id);
                Integer orderStatus = orderInfo.getOrderStatus();
                String tcWaybillNo = orderInfo.getTcWaybillNo();
                if (ObjectUtils.isEmpty(orderInfo)) {
                    throw new RuntimeException("订单不存在");
                } else {
                    if (!orderStatus.equals(OrderStatusEnum.TO_BE_PAID.getStatus()) && !orderStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus()) && !orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                        throw new BusinessException(ErrorEnum.NOT_WAIT_PAY_OR_PENDING_OR_PICKUP);
                    }
                }

                if (orderStatus.equals(OrderStatusEnum.PENDING_ITEMS.getStatus()) || orderStatus.equals(OrderStatusEnum.DOOR_TO_DOOR_PICKUP.getStatus())) {
                    //1.先让运控平台取消 2.查询是否退款过 3.退款 =》顺序不能调换
                    CancelWaybillRequest cancelWaybillRequest = new CancelWaybillRequest();
                    cancelWaybillRequest.setTcWaybillNo(tcWaybillNo);
                    cancelWaybillRequest.setCancelReason("取消订单");
                    JSONObject jsonObject = intraCityRest.cancelWaybill(cancelWaybillRequest);
                    if (!jsonObject.getBoolean("success")) {
                        logger.info(jsonObject.getString("errorMessage"));
                        throw new RuntimeException(jsonObject.getString("errorMessage"));
                    }
                    Bill bill = billRest.getByTcWaybillNo(tcWaybillNo, PayStatusEnum.TO_BE_SETTLED.getValue());
                    //支付成功状态才让退款,这是待结算状态才让退款
                    if (!ObjectUtils.isEmpty(bill)) {
                        //恢复额度
                        this.restoreCreditLimit(orderInfo.getPricePaid());
                        BillAddRequest billAddRequest = new BillAddRequest();
                        billAddRequest.setOrderId(orderInfo.getId());
                        billAddRequest.setTcWaybillNo(tcWaybillNo);
                        billAddRequest.setPricePaid(orderInfo.getPricePaid());
                        billAddRequest.setPayStatus(PayStatusEnum.CANCEL.getValue());
                        billAddRequest.setUpdateTime(date);
                        billAddRequest.setUserId(orderInfo.getUserId());
                        billAddRequest.setType(OrderTypeEnum.REFUND.getValue());
                        billRest.add(billAddRequest);
                        //收入记录的待结算改为取消
                        bill.setUpdateTime(date);
                        bill.setPayStatus(PayStatusEnum.CANCEL.getValue());
                        billMapper.updateById(bill);
                    }
                }
                orderInfo.setOrderStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());
                TaskStatusLog taskStatusLog = new TaskStatusLog();
                taskStatusLog.setStatus(OrderStatusEnum.CANCEL_BEFORE_PAYMENT.getStatus());

                orderInfo.setUpdateTime(date);
//            orderInfo.setType(OrderTypeEnum.REFUND.getValue());
                orderInfoMapper.updateById(orderInfo);

                taskStatusLog.setProcessedBy(processedBy);
                taskStatusLog.setTaskId(orderInfo.getId());
                taskStatusLog.setCreateTime(date);
                taskStatusLog.setUpdateTime(date);
                taskStatusLog.setUserId(orderInfo.getUserId());
                taskStatusLogRest.add(taskStatusLog);
                return date;
            }
            return null;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (!ObjectUtils.isEmpty(lock)) {
                // 释放锁
                lock.unlock();
            }
        }

    }

    @Override
    public List<PrintDataResponse> getPrintData(Set<String> tcWaybillNos) {
        List<OrderInfo> orders = orderInfoRest.getOrdersInTcWaybillNos(tcWaybillNos);
        List<PrintDataResponse> printDataResponses = new ArrayList<>();
        List<String> takeoffConnIds = orders.stream().map(orderInfo -> orderInfo.getTakeoffConnId()).collect(Collectors.toList());
        List<String> landingConnIds = orders.stream().map(orderInfo -> orderInfo.getLandingConnId()).collect(Collectors.toList());
        takeoffConnIds.addAll(landingConnIds);
        List<TtTesTerminal> ttTesTerminals = ttTesTerminalRest.selectByConnIds(takeoffConnIds);
        for (OrderInfo order : orders) {
            PrintDataResponse printDataResponse = new PrintDataResponse();
            BeanUtils.copyProperties(order, printDataResponse);
            printDataResponse.setSenderTel(PhoneEncoderUtil.desensitization(phoneEncoderUtil.decryptString(order.getSenderTel())));
            printDataResponse.setReceiverTel(PhoneEncoderUtil.desensitization(phoneEncoderUtil.decryptString(order.getReceiverTel())));
            for (TtTesTerminal ttTesTerminal : ttTesTerminals) {
                if (order.getTakeoffConnId().equals(ttTesTerminal.getConnId())) {
                    printDataResponse.setTakeoffConnName(ttTesTerminal.getName());
                }
                if (order.getLandingConnId().equals(ttTesTerminal.getConnId())) {
                    printDataResponse.setLandingConnName(ttTesTerminal.getName());
                }

            }
            printDataResponses.add(printDataResponse);

        }
        return printDataResponses;
    }

    public void restoreCreditLimit(BigDecimal pricePaid) {
        String userId = JwtUtil.getUserId();
        UserCompany userCompany = userCompanyRest.getByUserId(userId);
        if (!ObjectUtils.isEmpty(userCompany)) {
            BigDecimal usedCreditLimit = userCompany.getUsedCreditLimit();
            // 已用的减去取消的
            usedCreditLimit = usedCreditLimit.subtract(pricePaid);
            userCompany.setUsedCreditLimit(usedCreditLimit);
            userCompany.setUpdateTime(new Date());
            userCompanyMapper.updateById(userCompany);
        }
    }

}
